package com.huawei.zyb.taskManager.domain.task.entity;

import com.huawei.zyb.taskManager.domain.project.valueobject.ProjectId;
import com.huawei.zyb.taskManager.domain.requirement.valueobject.RequirementId;
import com.huawei.zyb.taskManager.domain.developer.valueobject.DeveloperId;
import com.huawei.zyb.taskManager.domain.task.valueobject.*;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 任务聚合根
 * 管理单个任务的完整生命周期和层级关系
 */
public class Task {
    private TaskId id;
    private TaskTitle title;
    private TaskDescription description;
    private TaskStatus status;
    private TaskProgress progress;
    private TaskPriority priority;
    private String assigneeId; // 指派人ID
    private Long requirementId; // 所属需求ID
    private TaskId parentTaskId; // 父任务ID（可选）
    private TaskLevel level;
    private EstimatedHours estimatedHours;
    private ActualHours actualHours;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    // 私有构造函数，强制使用工厂方法
    private Task() {}

    /**
     * 创建新任务（主任务）
     */
    public static Task create(
            TaskId id,
            TaskTitle title,
            TaskDescription description,
            TaskStatus status,
            TaskPriority priority,
            Long requirementId,
            String assigneeId,
            EstimatedHours estimatedHours,
            TaskProgress progress,
            ActualHours actualHours) {
        
        Objects.requireNonNull(requirementId, "任务必须关联到有效的需求");
        
        Task task = new Task();
        task.id = id;
        task.title = title;
        task.description = description;
        task.status = status != null ? status : TaskStatus.TODO;
        
        // 根据状态自动设置正确的进度，确保符合数据库约束
        if (task.status == TaskStatus.TODO) {
            task.progress = TaskProgress.zero();
        } else if (task.status == TaskStatus.COMPLETED) {
            task.progress = TaskProgress.completed();
        } else {
            // 对于IN_PROGRESS、PAUSED、CANCELLED状态，使用传入的进度或默认为0
            task.progress = progress != null ? progress : TaskProgress.zero();
        }
        
        task.priority = priority;
        task.assigneeId = assigneeId;
        task.requirementId = requirementId;
        task.parentTaskId = null;
        task.level = TaskLevel.LEVEL_1;
        task.estimatedHours = estimatedHours != null ? estimatedHours : EstimatedHours.zero();
        task.actualHours = actualHours != null ? actualHours : ActualHours.zero();
        task.createdAt = LocalDateTime.now();
        task.updatedAt = LocalDateTime.now();
        
        return task;
    }

    /**
     * 创建子任务
     */
    public static Task createSubTask(
            TaskId id,
            TaskTitle title,
            TaskDescription description,
            TaskStatus status,
            TaskPriority priority,
            Long requirementId,
            String assigneeId,
            TaskId parentTaskId,
            TaskLevel level,
            EstimatedHours estimatedHours,
            TaskProgress progress,
            ActualHours actualHours) {
        
        Objects.requireNonNull(parentTaskId, "子任务的父任务不能为空");
        Objects.requireNonNull(requirementId, "任务必须关联到有效的需求");
        
        if (level.isRootLevel()) {
            throw new IllegalArgumentException("子任务不能使用主任务层级");
        }
        
        Task task = new Task();
        task.id = id;
        task.title = title;
        task.description = description;
        task.status = status != null ? status : TaskStatus.TODO;
        
        // 根据状态自动设置正确的进度，确保符合数据库约束
        if (task.status == TaskStatus.TODO) {
            task.progress = TaskProgress.zero();
        } else if (task.status == TaskStatus.COMPLETED) {
            task.progress = TaskProgress.completed();
        } else {
            // 对于IN_PROGRESS、PAUSED、CANCELLED状态，使用传入的进度或默认为0
            task.progress = progress != null ? progress : TaskProgress.zero();
        }
        
        task.priority = priority;
        task.assigneeId = assigneeId;
        task.requirementId = requirementId;
        task.parentTaskId = parentTaskId;
        task.level = level;
        task.estimatedHours = estimatedHours != null ? estimatedHours : EstimatedHours.zero();
        task.actualHours = actualHours != null ? actualHours : ActualHours.zero();
        task.createdAt = LocalDateTime.now();
        task.updatedAt = LocalDateTime.now();
        
        return task;
    }

    /**
     * 从持久化数据恢复任务对象
     */
    public static Task restore(
            TaskId id,
            TaskTitle title,
            TaskDescription description,
            TaskStatus status,
            TaskProgress progress,
            TaskPriority priority,
            TaskLevel level,
            String assigneeId,
            Long requirementId,
            TaskId parentTaskId,
            EstimatedHours estimatedHours,
            ActualHours actualHours,
            LocalDateTime createdAt,
            LocalDateTime updatedAt) {
        
        Task task = new Task();
        task.id = id;
        task.title = title;
        task.description = description;
        task.status = status;
        task.progress = progress;
        task.priority = priority;
        task.level = level;
        task.assigneeId = assigneeId;
        task.requirementId = requirementId;
        task.parentTaskId = parentTaskId;
        task.estimatedHours = estimatedHours;
        task.actualHours = actualHours;
        task.createdAt = createdAt;
        task.updatedAt = updatedAt;
        
        return task;
    }

    /**
     * 更新任务状态
     */
    public void updateStatus(TaskStatus newStatus) {
        if (!this.status.canTransitionTo(newStatus)) {
            throw new IllegalStateException(
                String.format("任务状态不能从[%s]转换到[%s]", 
                    this.status.getDescription(), newStatus.getDescription())
            );
        }
        
        // 检查任务开始时是否已分配
        if (newStatus == TaskStatus.IN_PROGRESS && this.assigneeId == null) {
            throw new IllegalStateException("任务必须分配给开发者后才能开始");
        }
        
        // 状态转换时自动调整进度
        if (newStatus == TaskStatus.TODO) {
            this.progress = TaskProgress.zero();
        } else if (newStatus == TaskStatus.COMPLETED) {
            this.progress = TaskProgress.completed();
        }
        
        this.status = newStatus;
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 更新任务进度
     */
    public void updateProgress(TaskProgress newProgress) {
        newProgress.validateWithStatus(this.status);
        this.progress = newProgress;
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 更新预估工时
     */
    public void updateEstimatedHours(EstimatedHours hours) {
        this.estimatedHours = Objects.requireNonNull(hours, "预估工时不能为空");
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 更新实际工时
     */
    public void updateActualHours(ActualHours hours) {
        this.actualHours = Objects.requireNonNull(hours, "实际工时不能为空");
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 更新任务信息
     */
    public void updateInfo(TaskTitle title, TaskDescription description, TaskPriority priority) {
        this.title = Objects.requireNonNull(title, "任务标题不能为空");
        this.description = Objects.requireNonNull(description, "任务描述不能为空");
        this.priority = Objects.requireNonNull(priority, "任务优先级不能为空");
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 分配任务给开发者
     */
    public void assignTo(String developerId) {
        if (!canBeAssigned()) {
            throw new IllegalStateException("任务当前状态不允许分配: " + this.status.getDescription());
        }
        this.assigneeId = developerId;
        this.status = TaskStatus.IN_PROGRESS;
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 检查是否可以创建子任务
     */
    public boolean canCreateSubTask() {
        return this.level.canHaveSubTask();
    }

    /**
     * 获取下一级任务层级
     */
    public TaskLevel getNextSubTaskLevel() {
        return this.level.getNextLevel();
    }

    /**
     * 检查是否为子任务
     */
    public boolean isSubTask() {
        return this.parentTaskId != null;
    }

    /**
     * 检查是否已完成
     */
    public boolean isCompleted() {
        return this.status == TaskStatus.COMPLETED;
    }

    /**
     * 检查是否为终态
     */
    public boolean isFinalState() {
        return this.status.isFinalState();
    }

    /**
     * 检查是否可以分配
     */
    public boolean canBeAssigned() {
        return !this.status.isFinalState();
    }

    /**
     * 暂停任务
     */
    public void pause() {
        updateStatus(TaskStatus.PAUSED);
    }

    /**
     * 恢复任务
     */
    public void resume() {
        updateStatus(TaskStatus.IN_PROGRESS);
    }

    /**
     * 完成任务
     */
    public void complete() {
        updateStatus(TaskStatus.COMPLETED);
    }

    /**
     * 取消任务
     */
    public void cancel() {
        updateStatus(TaskStatus.CANCELLED);
    }

    // Getters
    public TaskId getId() { return id; }
    public TaskTitle getTitle() { return title; }
    public TaskDescription getDescription() { return description; }
    public TaskStatus getStatus() { return status; }
    public TaskProgress getProgress() { return progress; }
    public TaskPriority getPriority() { return priority; }
    public String getAssigneeId() { return assigneeId; }
    public Long getRequirementId() { return requirementId; }
    public TaskId getParentTaskId() { return parentTaskId; }
    public TaskLevel getLevel() { return level; }
    public EstimatedHours getEstimatedHours() { return estimatedHours; }
    public ActualHours getActualHours() { return actualHours; }
    public LocalDateTime getCreatedAt() { return createdAt; }
    public LocalDateTime getUpdatedAt() { return updatedAt; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Task task = (Task) obj;
        return Objects.equals(id, task.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public String toString() {
        return "Task{" +
                "id=" + id +
                ", title=" + title +
                ", status=" + status +
                ", progress=" + progress +
                ", level=" + level +
                "}";
    }
}